package com.hxz.graduationdesign;

import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class BiliUpVideoCrawler {
    public static void main(String[] args) {
        System.setProperty("webdriver.chrome.driver", "C:\\Program Files\\Google\\chromedriver-win64\\chromedriver.exe");

        ChromeOptions options = new ChromeOptions();
        options.addArguments("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36");
        // 无头模式
//        options.addArguments("--headless");
        // 禁用图片加载，提高速度
        options.addArguments("--blink-settings=imagesEnabled=false");

        WebDriver driver = new ChromeDriver(options);
        // 设置隐式等待时间
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

        try {
            String upId = "38719597";
            String upHomeUrl = "https://space.bilibili.com/" + upId + "/video";
            driver.get(upHomeUrl);

            WebDriverWait wait = new WebDriverWait(driver, 30);

            // 1. 首先爬取UP主基本信息
            crawlUpInfo(driver, wait, upId);

            // 2. 等待视频列表加载
            wait.until(ExpectedConditions.presenceOfElementLocated(
                    By.cssSelector("li.small-item.fakeDanmu-item")
            ));

            // 3. 滚动加载更多视频（如果需要）
            scrollToBottom(driver);

            // 4. 提取视频信息
            List<WebElement> videos = driver.findElements(
                    By.cssSelector("li.small-item.fakeDanmu-item")
            );

            System.out.println("\n============ 视频列表 ============");
            for (WebElement video : videos) {
                String title = video.findElement(By.cssSelector("a.title")).getText();
                String url = video.findElement(By.cssSelector("a.cover")).getAttribute("href");
                String playCount = video.findElement(By.cssSelector("span.play span")).getText();
                String uploadDate = video.findElement(By.cssSelector("span.time")).getText().trim();

                // 获取弹幕量
                String danmuCount = "N/A";
                try {
                    danmuCount = video.findElement(By.cssSelector("span.danmu span")).getText();
                } catch (NoSuchElementException e) {
                    System.out.println("无法获取弹幕量: " + e.getMessage());
                }

                // 获取视频时长
                String duration = "N/A";
                try {
                    duration = video.findElement(By.cssSelector("span.length")).getText();
                } catch (NoSuchElementException e) {
                    System.out.println("无法获取视频时长: " + e.getMessage());
                }

                System.out.println("标题: " + title);
                System.out.println("链接: " + url);
                System.out.println("播放量: " + playCount);
                System.out.println("弹幕量: " + danmuCount);
                System.out.println("时长: " + duration);
                System.out.println("发布日期: " + uploadDate);
                System.out.println("----------------------");
            }

        } catch (Exception e) {
            System.err.println("抓取失败，当前页面源码已保存到 error.html");
            savePageSource(driver, "error.html");
            e.printStackTrace();
        } finally {
            driver.quit();
        }
    }

    // 爬取UP主基本信息
    private static void crawlUpInfo(WebDriver driver, WebDriverWait wait, String upId) {
        try {
            // 等待UP主信息区域加载
            wait.until(ExpectedConditions.presenceOfElementLocated(
                    By.cssSelector("div.up-info")
            ));

            // 获取UP主名称
            String upName = driver.findElement(By.cssSelector("h1#h-name")).getText();

            // 获取粉丝数
            String fansCount = driver.findElement(By.cssSelector("span.n-data.fans")).getText();

            // 获取获赞数
            String likesCount = driver.findElement(By.cssSelector("span.n-data.likes")).getText();

            // 获取投稿数
            String videoCount = driver.findElement(By.xpath("//span[contains(text(),'投稿')]/following-sibling::span")).getText();

            // 获取个人简介
            String description = driver.findElement(By.cssSelector("p.desc")).getText();

            System.out.println("============ UP主信息 ============");
            System.out.println("UP主ID: " + upId);
            System.out.println("UP主名称: " + upName);
            System.out.println("粉丝数: " + fansCount);
            System.out.println("获赞数: " + likesCount);
            System.out.println("投稿数: " + videoCount);
            System.out.println("个人简介: " + description);
            System.out.println("================================");

        } catch (Exception e) {
            System.err.println("获取UP主信息失败: " + e.getMessage());
        }
    }

    // 滚动到页面底部（触发懒加载）
    private static void scrollToBottom(WebDriver driver) {
        JavascriptExecutor js = (JavascriptExecutor) driver;
        long lastHeight = (long) js.executeScript("return document.body.scrollHeight");

        int scrollAttempts = 0;
        final int MAX_SCROLL_ATTEMPTS = 5; // 最多滚动5次

        while (scrollAttempts < MAX_SCROLL_ATTEMPTS) {
            js.executeScript("window.scrollTo(0, document.body.scrollHeight);");
            try {
                Thread.sleep(2000); // 等待加载
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long newHeight = (long) js.executeScript("return document.body.scrollHeight");
            if (newHeight == lastHeight) {
                scrollAttempts++;
            } else {
                scrollAttempts = 0; // 重置计数器
            }
            lastHeight = newHeight;
        }
    }

    // 保存页面源码（用于调试）
    private static void savePageSource(WebDriver driver, String filename) {
        try {
            Files.write(Paths.get(filename), driver.getPageSource().getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}